package com.csot.ry.service.impl;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.BiMap;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.csot.common.core.text.Convert;
import com.csot.common.utils.ServletUtils;
import com.csot.config.Caches;
import com.csot.ry.domain.TCitySegment;
import com.csot.ry.domain.TCoarseSegment;
import com.csot.ry.util.CacheKitUtil;
import com.csot.ry.util.UserUtils;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.ehcache.CacheKit;
import com.csot.common.core.domain.entity.SysUser;
import com.csot.common.exception.ServiceException;
import com.csot.common.utils.DateUtils;
import com.csot.common.utils.SecurityUtils;
import com.csot.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.csot.ry.mapper.TCoarseSegmentMapper;
import com.csot.ry.service.ITCoarseSegmentService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 粗粒度ip段Service业务层处理
 *
 * @author 刘沙
 * @date 2022-05-31
 */
@Service
public class TCoarseSegmentServiceImpl implements ITCoarseSegmentService {
    private static final Logger log = LoggerFactory.getLogger(TCoarseSegmentServiceImpl.class);

    public static BiMap<String, String> ip_type = CacheKit.get("dict-data", "ip_type");
    public static BiMap<String, String> ip_city = CacheKit.get("dict-data", "ip_city");
    public static BiMap<String, String> ip_use_type = CacheKit.get("dict-data", "ip_use_type");
    public static BiMap<String, String> ip_status = CacheKit.get("dict-data", "ip_status");

    @Autowired
    private TCoarseSegmentMapper tCoarseSegmentMapper;

    /**
     * 查询粗粒度ip段
     *
     * @param id 粗粒度ip段主键
     * @return 粗粒度ip段
     */
    @Override
    public TCoarseSegment selectTCoarseSegmentById(Long id) {
        return tCoarseSegmentMapper.selectTCoarseSegmentById(id);
    }

    /**
     * 查询粗粒度ip段列表
     *
     * @param tCoarseSegment 粗粒度ip段
     * @return 粗粒度ip段
     */
    @Override
    public List<TCoarseSegment> selectTCoarseSegmentList(TCoarseSegment tCoarseSegment) {
        try {
            if (StrUtil.isNotEmpty(tCoarseSegment.getIpStart())) {
                tCoarseSegment.setIpStartI(NetUtil.ipv4ToLong(tCoarseSegment.getIpStart().trim()));
            }
            if (StrUtil.isNotEmpty(tCoarseSegment.getIpEnd())) {
                tCoarseSegment.setIpEndI(NetUtil.ipv4ToLong(tCoarseSegment.getIpEnd().trim()));
            }
        } catch (Exception e) {
            throw new ServiceException("起止IP不正确");
        }
        return tCoarseSegmentMapper.selectTCoarseSegmentList(tCoarseSegment);

    }

    /**
     * 新增粗粒度ip段
     *
     * @param tCoarseSegment 粗粒度ip段
     * @return 结果
     */
    @Override
    public int insertTCoarseSegment(TCoarseSegment tCoarseSegment) {
        tCoarseSegment.setCreateTime(DateUtils.getNowDate());
        tCoarseSegment.setIpStartI(NetUtil.ipv4ToLong(tCoarseSegment.getIpStart().trim()));
        tCoarseSegment.setIpEndI(NetUtil.ipv4ToLong(tCoarseSegment.getIpEnd().trim()));

        return tCoarseSegmentMapper.insertTCoarseSegment(tCoarseSegment);
    }

    /**
     * 修改粗粒度ip段
     *
     * @param tCoarseSegment 粗粒度ip段
     * @return 结果
     */
    @Override
    public int updateTCoarseSegment(TCoarseSegment tCoarseSegment) {
//        TCoarseSegment tCoarseSegmentOld = this.selectTCoarseSegmentById(tCoarseSegment.getId());
        // 修改只能在原段内进行
        long newIpStartI = NetUtil.ipv4ToLong(tCoarseSegment.getIpStart().trim());
        long newIpEndI = NetUtil.ipv4ToLong(tCoarseSegment.getIpEnd().trim());
        if (newIpEndI < newIpStartI) {
            throw new ServiceException("终止IP不能小于起始IP！");
        }

        List<?> repeatList1 = Db.find(
                "select 1 from t_coarse_segment where ( ( ip_start_i <= ? and ip_end_i >= ? ) or ( ip_start_i <=? and ip_end_i >= ? ) )  "
                        + "  and ip_city = ? and id != ?",
                newIpStartI, newIpStartI, newIpEndI, newIpEndI
                , tCoarseSegment.getIpCity(), tCoarseSegment.getId());
        if (repeatList1.size() > 0) {
            throw new ServiceException(
                    String.format("IP地址与其他IP段重复！"));
        }

        tCoarseSegment.setIpStartI(newIpStartI);
        tCoarseSegment.setIpEndI(newIpEndI);

//        if (tCoarseSegmentOld.getIpStartI() == newIpStartI && tCoarseSegmentOld.getIpEndI() > newIpEndI) {
//            TCoarseSegment tTotalSegmentNew = getCoarseSegmentOld(tCoarseSegmentOld);
//            tTotalSegmentNew.setIpStartI(newIpEndI + 1);
//            tTotalSegmentNew.setIpStart(NetUtil.longToIpv4(newIpEndI + 1));
//            tTotalSegmentNew.setId(null);
//            this.insertTCoarseSegment(tTotalSegmentNew);
//        } else if (tCoarseSegmentOld.getIpStartI() < newIpStartI && tCoarseSegmentOld.getIpEndI() == newIpEndI) {
//            TCoarseSegment tTotalSegmentNew = getCoarseSegmentOld(tCoarseSegmentOld);
//            tTotalSegmentNew.setIpEndI(newIpStartI - 1);
//            tTotalSegmentNew.setIpEnd(NetUtil.longToIpv4(newIpStartI - 1));
//            tTotalSegmentNew.setId(null);
//            this.insertTCoarseSegment(tTotalSegmentNew);
//        } else if (tCoarseSegmentOld.getIpStartI() < newIpStartI && tCoarseSegmentOld.getIpEndI() > newIpEndI) {
//            TCoarseSegment tTotalSegmentNew1 = getCoarseSegmentOld(tCoarseSegmentOld);
//            tTotalSegmentNew1.setIpEndI(newIpStartI - 1);
//            tTotalSegmentNew1.setIpEnd(NetUtil.longToIpv4(newIpStartI - 1));
//            tTotalSegmentNew1.setId(null);
//            this.insertTCoarseSegment(tTotalSegmentNew1);
//            TCoarseSegment tTotalSegmentNew2 = getCoarseSegmentOld(tCoarseSegmentOld);
//            tTotalSegmentNew2.setIpStartI(newIpEndI + 1);
//            tTotalSegmentNew2.setIpStart(NetUtil.longToIpv4(newIpEndI + 1));
//            tTotalSegmentNew2.setId(null);
//            this.insertTCoarseSegment(tTotalSegmentNew2);
//        }
        tCoarseSegment.setUpdateTime(DateUtils.getNowDate());
        return tCoarseSegmentMapper.updateTCoarseSegment(tCoarseSegment);
    }

    // 克隆没好用，只好写一次了
    private TCoarseSegment getCoarseSegmentOld(TCoarseSegment told) {
        TCoarseSegment tnew = new TCoarseSegment();
        tnew.setIpStart(told.getIpStart());
        tnew.setIpStartI(told.getIpStartI());
        tnew.setIpEnd(told.getIpEnd());
        tnew.setIpEndI(told.getIpEndI());
        tnew.setIpType(told.getIpType());
        tnew.setIpCity(told.getIpCity());
        tnew.setIpUser(told.getIpUser());
        tnew.setIpStatus(told.getIpStatus());
        tnew.setIpManagement(told.getIpManagement());
        tnew.setCreateBy(told.getCreateBy());
        tnew.setCreateTime(told.getCreateTime());
        tnew.setRemark(told.getRemark());
        tnew.setIpSubnet(told.getIpSubnet());
        tnew.setIpEquipment(told.getIpEquipment());
        tnew.setIpGateway(told.getIpGateway());
        return tnew;
    }

    /**
     * 批量删除粗粒度ip段
     *
     * @param ids 需要删除的粗粒度ip段主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteTCoarseSegmentByIds(Long[] ids) {
        Db.delete("DELETE FROM  t_coarse_ip WHERE ip_segment_id IN (" + ArrayUtil.join(ids, ",") + ")");
        return tCoarseSegmentMapper.deleteTCoarseSegmentByIds(ids);
    }

    /**
     * 删除粗粒度ip段信息
     *
     * @param id 粗粒度ip段主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteTCoarseSegmentById(Long id) {
        Db.delete("DELETE FROM  t_coarse_ip WHERE ip_segment_id in = ", id);
        return tCoarseSegmentMapper.deleteTCoarseSegmentById(id);
    }

    /**
     * 导入粗粒度ip段数据
     *
     * @param tCoarseSegmentList 地市地址段管理列表
     * @param isUpdateSupport    是否更新支持，如果已存在，则进行更新数据
     * @return 结果
     */
    @Override
    @Transactional
    public String importCoarseSegment(List<TCoarseSegment> tCoarseSegmentList, Boolean isUpdateSupport) {
        if (StringUtils.isNull(tCoarseSegmentList) || tCoarseSegmentList.size() == 0) {
            throw new ServiceException("导入粗粒度ip段数据不能为空！");
        }
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Long deptid = user.getDeptId();
        Long pdeptid = user.getDept().getParentId();

        String city_zh = Caches.getDeptName(String.valueOf(pdeptid));
        String city_e = CacheKitUtil.ip_dept.get(String.valueOf(pdeptid));
        // 验证数据本身是否重复
        // todo 用户城市与传入城市进行验证

        for (int i = 0; i < tCoarseSegmentList.size(); i++) {
            TCoarseSegment tcs = tCoarseSegmentList.get(i);
            if (StrUtil.isBlank(tcs.getIpType())) {
                tcs.setIpType("ip_area");
            }
            try {
                tcs.setIpStart(tcs.getIpStart().trim());
                if (tcs.getIpStart().contains("/")) {
                    String[] ips = tcs.getIpStart().split("/");
                    tcs.setIpStart(ips[0].trim());
                    tcs.setIpStartI(NetUtil.ipv4ToLong(ips[0].trim()));
                    tcs.setIpEndI(Ipv4Util.getEndIpLong(ips[0].trim(), Convert.toInt(ips[1])));
                    tcs.setIpEnd(NetUtil.longToIpv4(tcs.getIpEndI()));
                    tcs.setIpEndI(NetUtil.ipv4ToLong(tcs.getIpEnd()));
                } else {
                    tcs.setIpEnd(tcs.getIpEnd().trim());
                    tcs.setIpStartI(NetUtil.ipv4ToLong(tcs.getIpStart().trim()));
                    tcs.setIpEndI(NetUtil.ipv4ToLong(tcs.getIpEnd().trim()));
                }

                tcs.setIpCity(ip_city.getKey(tcs.getIpCity()));
                tcs.setIpUseType(ip_use_type.getKey(tcs.getIpUseType()));
                if (StrUtil.isEmpty(tcs.getIpStatus())) {
                    tcs.setIpStatus("on");
                } else {
                    tcs.setIpStatus(ip_status.getKey(tcs.getIpStatus()));
                }
                tcs.setCreateBy(user.getUserName());
                tcs.setRecordStatus(CacheKitUtil.ip_record.getKey(tcs.getRecordStatus()));
                tcs.setCreateTime(new Date());

            } catch (Exception e) {
                log.error(e.getMessage());
                throw new ServiceException(
                        String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart() + "或" + tcs.getIpEnd(), "数据格式不正确"));
            }
            if (StringUtils.isBlank(tcs.getIpCity())) {
                throw new ServiceException(
                        String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart(), "地市不能为空"));
            }
            if (deptid != 100) {
                if (!tcs.getIpCity().equals(city_e)) {
                    throw new ServiceException(String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart(),
                            "只能上传'" + city_zh + "'市数据"));
                }
            }

////            String iptype = "ip_area";
//            List<?> repeatList = Db.find(
//                    "select distinct id from t_total_segment where ip_start_i <= ? and ip_end_i >= ? and ip_type = ? and ip_city = ?",
//                    tcs.getIpStartI(), tcs.getIpEndI(), tcs.getIpType(), tcs.getIpCity());
//            if (repeatList.size() != 1) {
//                throw new ServiceException(
//                        String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart(), "起始地址和终止地址在省地址中未分配"));
//            }


            List<?> startList = Db.find(
                    "select distinct id from t_total_segment where ip_start_i <= ? and ip_end_i >= ? and ip_type = ? and ip_city = ?",
                    tcs.getIpStartI(), tcs.getIpStartI(), tcs.getIpType(), tcs.getIpCity());

            List<?> endList = Db.find(
                    "select distinct id from t_total_segment where ip_start_i <= ? and ip_end_i >= ? and ip_type = ? and ip_city = ?",
                    tcs.getIpEndI(), tcs.getIpEndI(), tcs.getIpType(), tcs.getIpCity());

            if (CollUtil.isEmpty(startList) || CollUtil.isEmpty(endList)) {
                throw new ServiceException(
                        String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart(), "起始地址或终止地址在省地址中未分配"));
            }


            List<?> repeatList1 = Db.find(
                    "select 1 from t_coarse_segment where (( ( ip_start_i between ? and ? ) or ( ip_end_i between ? and ? ) ) or "
                            + " ( ip_start_i >= ? and ip_end_i <= ? )) and ip_city = ? ",
                    tcs.getIpStartI(), tcs.getIpEndI(), tcs.getIpStartI(), tcs.getIpEndI(), tcs.getIpStartI(),
                    tcs.getIpEndI(), tcs.getIpCity());
            if (repeatList1.size() > 0) {
                throw new ServiceException(
                        String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs.getIpStart(), "该地址段部分已导入"));
            }

            tcs.setCreateTime(new Date());
            tcs.setCreateBy(user.getUserName());
        }

        for (int i = 0; i < tCoarseSegmentList.size(); i++) {
            TCoarseSegment tcs1 = tCoarseSegmentList.get(i);
            for (int j = i + 1; j < tCoarseSegmentList.size(); j++) {
                TCoarseSegment tcs2 = tCoarseSegmentList.get(j);
                if (tcs1.getIpStartI() > tcs2.getIpStartI() && tcs1.getIpStartI() < tcs2.getIpEndI()) {
                    throw new ServiceException(String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs1.getIpStart(),
                            "起始地址和第" + (j + 2) + "行有重复"));
                }
                if (tcs1.getIpEndI() < tcs2.getIpEndI() && tcs1.getIpEndI() > tcs2.getIpStartI()) {
                    throw new ServiceException(String.format("第%d行数据异常，终止地址为：%s,异常原因：%s", i + 2, tcs1.getIpEnd(),
                            "终止地址和第" + (j + 2) + "行有重复"));
                }
                if (tcs1.getIpStartI() <= tcs2.getIpStartI() && tcs1.getIpEndI() >= tcs2.getIpEndI()) {
                    throw new ServiceException(String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2, tcs1.getIpStart(),
                            "起始地址和第" + (j + 2) + "行有重复"));
                }
            }
        }


        for (int i = 0; i < tCoarseSegmentList.size(); i++) {
            try {
                this.insertTCoarseSegment(tCoarseSegmentList.get(i));
            } catch (Exception e) {
                log.error("", e);
                throw new ServiceException(String.format("第%d行数据异常，起始地址为：%s,异常原因：%s", i + 2,
                        tCoarseSegmentList.get(i).getIpStart(), e.getMessage()));
            }
        }
        return "数据已全部导入成功！";
    }

    private boolean checkCoarseSegmentIsNotExist(List<TCoarseSegment> tCoarseSegmentList) {
        boolean bresult = false;
        for (TCoarseSegment tCoarseSegment : tCoarseSegmentList) {
            long start = NetUtil.ipv4ToLong(tCoarseSegment.getIpStart().trim());
            long end = NetUtil.ipv4ToLong(tCoarseSegment.getIpEnd().trim());
            List<Record> recordList = Db.find(
                    "SELECT count(1) as c FROM t_total_ip  WHERE  ip_address_i BETWEEN ? AND ? " + " AND ip_type = ? "
                            + " AND  ip_city = ? ",
                    start, end, tCoarseSegment.getIpType(), tCoarseSegment.getIpCity());
            if (recordList.size() > 0 && recordList.get(0).getLong("c") != (end - start + 1)) {
                return true;
            }
        }
        return bresult;
    }

    // 验证传进来的数据是否有重复
    private boolean checkCoarseSegmentIsRepeat(List<TCoarseSegment> CoarseSegmentList) {
        boolean bresult = false;
        TCoarseSegment tTotalSegment_i = null;
        TCoarseSegment tTotalSegment_j = null;
        for (int i = 0; i < CoarseSegmentList.size() - 1; i++) {
            tTotalSegment_i = CoarseSegmentList.get(i);
            if (tTotalSegment_i.getIpEndI() < tTotalSegment_i.getIpStartI()) {
                bresult = true;
                return bresult;
            }
            for (int j = i + 1; j < CoarseSegmentList.size(); j++) {
                tTotalSegment_j = CoarseSegmentList.get(j);
                if ((tTotalSegment_i.getIpStartI() >= tTotalSegment_j.getIpStartI()
                        && tTotalSegment_i.getIpStartI() <= tTotalSegment_j.getIpEndI())
                        || (tTotalSegment_i.getIpEndI() >= tTotalSegment_j.getIpStartI()
                        && tTotalSegment_i.getIpEndI() <= tTotalSegment_j.getIpEndI())
                        && tTotalSegment_i.getIpType().equals(tTotalSegment_j.getIpType())) {
                    bresult = true;
                    return bresult;
                }
            }
        }
        return bresult;
    }

    private List<TCoarseSegment> getTotalSegmentList(List<TCoarseSegment> tTCoarseSegmentList, SysUser user) {
        List<TCoarseSegment> rList = tTCoarseSegmentList;
        Date date = new Date();
        rList.forEach(ts -> {
            if (ts.getIpStart().contains("/") && StrUtil.isEmpty(ts.getIpEnd())) {
                List<String> ipList = Ipv4Util.list(ts.getIpStart().trim(), true);
                ts.setIpStart(ipList.get(0).trim());
                ts.setIpStartI(NetUtil.ipv4ToLong(ipList.get(0).trim()));
                ts.setIpEnd(ipList.get(ipList.size() - 1));
                ts.setIpEndI(NetUtil.ipv4ToLong(ipList.get(ipList.size() - 1)));
            } else {
                ts.setIpStartI(NetUtil.ipv4ToLong(ts.getIpStart().trim()));
                ts.setIpEndI(NetUtil.ipv4ToLong(ts.getIpEnd().trim()));
            }
//            ts.setIpType(ip_type.getKey(ts.getIpType()));
            ts.setIpCity(ip_city.getKey(ts.getIpCity()));
            ts.setIpUseType(ip_use_type.getKey(ts.getIpUseType()));
            ts.setIpStatus(ip_status.getKey(ts.getIpStatus()));
            ts.setCreateBy(user.getNickName());
            ts.setRecordStatus(CacheKitUtil.ip_record.getKey(ts.getRecordStatus()));
            ts.setCreateTime(date);
        });
        return rList;
    }
}
